package com.udi.project.tool.utils;


import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * @author jialong
 * @date 2021/06/21
 * @description:
 **/
public class DesUtil {

    private static final String DES_ALGORITHM = "DES";

    /**
     * DES??
     * @param plainData ?????
     * @param secretKey ????
     * @return ???????
     * @throws Exception
     */
    public static String encryption(String plainData, String secretKey) throws Exception {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(DES_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, generateKey(secretKey));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        try {
            // ????????javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher???
            // ???????????????????
            byte[] buf = cipher.doFinal(plainData.getBytes());
            return Base64Utils.encode(buf);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new Exception("IllegalBlockSizeException", e);
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new Exception("BadPaddingException", e);
        }
    }


    /**
     * DES??
     * @param secretData ?????
     * @param secretKey  ????
     * @return ?????
     * @throws Exception
     */
    public static String decryption(String secretData, String secretKey) throws Exception {
        Cipher cipher;
        try {
            cipher = Cipher.getInstance(DES_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, generateKey(secretKey));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new Exception("NoSuchAlgorithmException", e);
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            throw new Exception("NoSuchPaddingException", e);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
            throw new Exception("InvalidKeyException", e);
        }
        try {
            byte[] buf = cipher.doFinal(Base64Utils.decode(secretData.toCharArray()));
            return new String(buf);
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
            throw new Exception("IllegalBlockSizeException", e);
        } catch (BadPaddingException e) {
            e.printStackTrace();
            throw new Exception("BadPaddingException", e);
        }
    }

    /**
     * ??????
     *
     * @param secretKey
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     */
    private static SecretKey generateKey(String secretKey)
            throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM);
        DESKeySpec keySpec = new DESKeySpec(secretKey.getBytes("gbk"));
        keyFactory.generateSecret(keySpec);
        return keyFactory.generateSecret(keySpec);
    }


    static private class Base64Utils {
        static private char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
                .toCharArray();
        static private byte[] codes = new byte[256];
        static {
            for (int i = 0; i < 256; i++)
                codes[i] = -1;
            for (int i = 'A'; i <= 'Z'; i++)
                codes[i] = (byte) (i - 'A');
            for (int i = 'a'; i <= 'z'; i++)
                codes[i] = (byte) (26 + i - 'a');
            for (int i = '0'; i <= '9'; i++)
                codes[i] = (byte) (52 + i - '0');
            codes['+'] = 62;
            codes['/'] = 63;
        }

        /**
         * ????????base64??
         */
        static private String encode(byte[] data) {
            char[] out = new char[((data.length + 2) / 3) * 4];
            for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
                boolean quad = false;
                boolean trip = false;
                int val = (0xFF & (int) data[i]);
                val <<= 8;
                if ((i + 1) < data.length) {
                    val |= (0xFF & (int) data[i + 1]);
                    trip = true;
                }
                val <<= 8;
                if ((i + 2) < data.length) {
                    val |= (0xFF & (int) data[i + 2]);
                    quad = true;
                }
                out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
                val >>= 6;
                out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
                val >>= 6;
                out[index + 1] = alphabet[val & 0x3F];
                val >>= 6;
                out[index + 0] = alphabet[val & 0x3F];
            }

            return new String(out);
        }

        /**
         * ?base64????????????
         */
        static private byte[] decode(char[] data) {
            int len = ((data.length + 3) / 4) * 3;
            if (data.length > 0 && data[data.length - 1] == '=')
                --len;
            if (data.length > 1 && data[data.length - 2] == '=')
                --len;
            byte[] out = new byte[len];
            int shift = 0;
            int accum = 0;
            int index = 0;
            for (int ix = 0; ix < data.length; ix++) {
                int value = codes[data[ix] & 0xFF];
                if (value >= 0) {
                    accum <<= 6;
                    shift += 6;
                    accum |= value;
                    if (shift >= 8) {
                        shift -= 8;
                        out[index++] = (byte) ((accum >> shift) & 0xff);
                    }
                }
            }
            if (index != out.length)
                throw new Error("miscalculated data length!");
            return out;
        }
    }


    public static void main(String[] args) throws Exception {
        String str =  decryption("4sUJpeSuUDKrMLswlrDnmO8+gkGIrtbt3yoHjM94w5+6H9Q5YiaTPvIAvyfu2EmUJBEW2UWh/34ootpwfcY7+N1Lgxp3qxmceDGqhOhhyFYmzPZHQr5QfEF48f2NCSkKqHobH259hvY0MYPbtvNY/i0Mydc1AXaiCWntcSX3eaRfaYwD6kG4vDp0cS6guQdZ8OlmmB4e3oNhzR44Tk5fK13px2CLw5ApAMGWD/pUjqpjoQn+9ITOLLjdlFAKK2CKQlJS/wqlU6qmDAWJ8hCZrwuhUwFu+eDXleO609+QgvJB5suzNeGG71xM/8v6c+Asrvn5L8oc/CPgR2ItkFSf01Hq2SI+EwTPqmKKQMu14skVJ8J5PlJ5nziUtsIyR+pTv7132dmb8ZiDKV1nlZ5iLD4QIYrb8B8sfHWoX3zLE9OjyQi1BLRY+D0kIqesqmXdjL4ldt2eou5H2YWRgceQ0a5vieqb9JS26PV5drIGxi53GutJgkA2EEAQvVLf0JzsEwyhzmiVcY91LtpSApcIhQlLkcTi3GQahJGX5xEZ4d8iPdqDE6LpjRQWkwRVEsoZw3sMJum6tC/ZcdFBkKl0OBtR481F23Sm0qtR5u0TAU7b6Slp7Zfg/RYG/Hs0ZyRW2BciqgCptuymYarIF1o6grH9A/VnthOKsvbmRvopkzCibFLd34gL5MvakUXRIGhjQjgv2zmDWehD0T84A5jNalIW15d44bUBFTJcrUzRjY1oOCPo780TIyYTXDWXZ6Ovelscwkouw/7kv4l4n60X4YPsXn+cA4+HwJ6m9H9GtuGtiJnN4Ki+rAZ+Bkk1aE1Nt0Twd2fuVMVsbyDnUsPys92X2PCGRE6lu6sJo6IcYEedfDV9m8PtiluLxPYMyU1/J03fJQjebe226NUqenmFbu4l3+gIocSV8OlmmB4e3oMzA+DTQ3JKUHoQfrjkdB6W2QHuh5sybjpKYG01hLoNsG3dXWMSmzQ8gyldZ5WeYiyTNByRJGPNuXpa2IXTE55lwUlEe43lidK9+KTDUIKxwcWbWIY/S0GlSeXiGEYqsUSyirragIadoR1vZO4DpQGVtDKrTRYK39wZULLPJrEN1uEr5UlGf57ULcL5CfnOUT4i4qHF6Lsg4zxqN2IY3oyU7NVlIddXV9mLTqP3+HQx6l0uo1Y6Iu2DO5eIShnm0ETQl5DRg/405bs1QjMPgx0dS/WMhTXeCQlAy/SygEUhDZ4jPw8JKfjkhgfaJg0Oo0UNEEy2XVJssMKJkj3p0jfr3g9UBhe8jWSSjz+4dfwtPB7srwAICl0qds7qRxI/syGibFLd34gL5MvakUXRIGhjttrYi0eyMjp6lOxmJ4TKnyzL4PiVTCheL4DgeO1pLQnH9hi8RRjfpIDuH+ZgN4gnqzC7MJaw55hAvaCVgd+Fln1JJ7Kys3fX0vpkCHzzY+3yAL8n7thJlJ2cwJnC5Ah2qhXqOYlls0ZsbyDnUsPysyjJU78Wt6ADJDofJOHrjIEtspNiTktUg3JRk1GC8vVNCvSvKuzXqK0v7z5jgVQxhtNlEbx0+ef2X2mMA+pBuLw/Qn/mT5rXmTkNQBrmQJvNvcRPZdyUpKl+f71GMp303DW2v4nlVkuZzQZTfLIrOVDm1hHcCI3/1XSUn0FiCivS8ww1rgmBkwjNNZ1hmWRVmnwWQ0/VGKK3xvItXkn4cRI24SS4OgIZ2q75+S/KHPwjXbFbKiWCaAZbBDyQ0SGG0CTnvz5PN8UNTyZx1Jem54AJN1eqzPXoDATMmUbWY3qiLxBvqQyvvHTMnZmsQaG42dv97xMfPXp8M+U7fiY6Tb/VS1ThrxJto3tuEABF+Qen1zWoQYR1ncdZYnyiXCvyiDDjcTv7J6bm7LEjWHSL70fCv7mndprTbvV3I+KYkWT0HbdzFMSk5axta4eX3I/lztTUiGerEPOB96Dd8NsDk5uBIQnF5PDCcctGBkeIJ3X4H2os0CJVhFfBokFDy6XA1tkRLB8n4ygwX3yKG3uzmy/FlJHYYJP05Y0HAU5mzCsFtGR/v1SCGNFHCYC7U5TC9J77mElpet4+Iw+yoMi7JeTZESwfJ+MoMC4Ljo/pcb5k/ZEv8dADxWVoFOoH6heKRfH5cy7e/Q7unW/vT0LeppU=","zhenpingxianyiyuan@erp");
        System.out.println(str);
    }
}